package com.qd.system.service.msg.server.send;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.cdqidi.core.weixinmanager.model.TemplateMsgDetailed;
import com.cdqidi.core.weixinmanager.service.TemplateMsgDetailedService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.qd.common.sys.domain.entity.msg.MsgReceiveContentDTO;
import com.qd.common.sys.domain.sendmsg.MsgContentProperty;
import com.qd.common.sys.domain.sendmsg.PersonMsg;
import com.qd.system.model.MsgReceive;
import com.qd.system.service.msg.base.MsgReceiveContentService;
import com.qd.system.service.msg.event.SmsTemplateEvent;
import com.qd.system.service.msg.server.MsgProcess;
import com.qd.system.sms.ISmsService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 发送短信
 *
 * @author sjk
 */
@Component
@AllArgsConstructor
@Slf4j
public class SmsTemplateService {

    private final ISmsService smsService;
    private final MsgReceiveContentService msgReceiveContentService;
    private final ObjectMapper objectMapper;
    @Resource
    private TemplateMsgDetailedService templateMsgDetailedService;


    @Async
    @EventListener(classes = SmsTemplateEvent.class)
    @Transactional(readOnly = true)
    public void doExec(SmsTemplateEvent smsTemplateEvent) {
        PersonMsg personMsg = (PersonMsg) smsTemplateEvent.getSource();
        try {
            String mobile = personMsg.getMsgProperties().getProp("mobile").toString();
            if (!StringUtils.hasLength(mobile)) {
                buildStatusLog(12, personMsg);
                log.error("手机号空无法发送,id:{},content:{}", personMsg.getId(), personMsg.getMsgContent().getContent());
                return;
            }
            String signName = personMsg.getMsgProperties().getProp("signName").toString();
            if (!StringUtils.hasLength(signName)) {
                buildStatusLog(13, personMsg);
                log.error("短信签名为空无法发送,id:{},content:{}", personMsg.getId(), personMsg.getMsgContent().getContent());
                return;
            }
            String templateShorId = personMsg.getMsgProperties().getProp("WxTempId").toString();
            if (!StringUtils.hasLength(templateShorId)) {
                //disstatus 11 微信模版配置为空
                buildStatusLog(11, personMsg);
                log.error("短信模板ID为空无法发送,id:{},content:{}", personMsg.getId(), personMsg.getMsgContent().getContent());
                return;
            }
            TemplateMsgDetailed templateMsgDetailed = buildTemplateId(templateShorId, personMsg);
            if (null == templateMsgDetailed) {
                return;
            }
            try {
                ObjectNode objectNode = objectMapper.createObjectNode();
                Map<String, MsgContentProperty> properties = personMsg.getMsgReceiveCustomProperties().getProperties();
                for (String key : properties.keySet()) {
                    objectNode.put(key, properties.get(key).getValue());
                }
                String msgId = smsService.sendSms(mobile, templateMsgDetailed.getTemplateId(), objectNode.toString(), signName);
                if (!StringUtils.hasLength(msgId)) {
                    buildStatusLog(15, null, mobile, personMsg);
                    log.error("短信发送失败");
                } else {
                    buildStatusLog(0, msgId, mobile, personMsg);
                }
            } catch (Exception e) {
                buildStatusLog(17, personMsg);
                log.error("其他异常错误", e);
            }
        } finally {
            personMsg.free();
        }
    }

    private void buildStatusLog(int status, PersonMsg personMsg) {
        buildStatusLog(status, null, null, personMsg);
    }


    private void buildStatusLog(int status, String msgId, String mobile, PersonMsg personMsg) {
        String receiveId = IdWorker.getIdStr();
        MsgReceive msgReceive = new MsgReceive();
        msgReceive.setReceiveId(receiveId);
        if (StringUtils.hasLength(msgId)) {
            msgReceive.setMsgId(msgId);
        }
        msgReceive.setMobile(mobile);
        msgReceive.setSendTime(LocalDateTime.now());
        msgReceive.setMsgSubId(personMsg.getFromMsgSubId());
        msgReceive.setMsgType(personMsg.getMsgContent().getType());
        msgReceive.setMsgEvent(personMsg.getMsgContent().getEvent());
        msgReceive.setFromUser(personMsg.getId());
        msgReceive.setFromUserType((int) personMsg.getClassify());
        msgReceive.setToUser(personMsg.getId());
        msgReceive.setAddTime(msgReceive.getSendTime());
        msgReceive.setStatus(status);

        MsgProcess.getInstance().addReceiveLog(msgReceive);

        buildReceiveContent(personMsg, receiveId);

    }

    public void buildReceiveContent(PersonMsg personMsg, String receiveId) {
        String templateShorId = personMsg.getMsgProperties().getProp("WxTempId").toString();
        MsgReceiveContentDTO contentLogDto = personMsg.getMsgReceiveContent();
        contentLogDto.setReceiveId(receiveId);
        contentLogDto.setTempId(templateShorId);
        contentLogDto.setAddTime(LocalDateTime.now());
        MsgProcess.getInstance().addReceiveContentLog(msgReceiveContentService.dtoToModel(contentLogDto));
    }

    /**
     * 根据templateShorId获得模板ID
     *
     * @param templateShorId templateShorId
     * @param personMsg      前端数据
     * @return templateId
     */
    private TemplateMsgDetailed buildTemplateId(String templateShorId, PersonMsg personMsg) {
        TemplateMsgDetailed template = templateMsgDetailedService.getTemplate(templateShorId, personMsg.getAppId());
        if (null == template) {
            //disstatus 12 微信配置错误
            buildStatusLog(12, personMsg);
            log.error("短信配置错误,templateShorId:{}", templateShorId);
            return null;
        }
        return template;
    }
}
